import { useSyncExternalStore } from "react";

interface StoreApi<T> {
  setState: (
    partial: T | Partial<T> | { _(state: T): T | Partial<T> }["_"],
    replace?: boolean | undefined
  ) => void;
  getState: () => T;
  subscribe: (listener: (state: T, prevState: T) => void) => () => void;
  destroy: () => void;
}

type StateCreator<T> = (
  setState: StoreApi<T>["setState"],
  getState: StoreApi<T>["getState"]
) => T;

type ExtractState<S> = S extends { getState: () => infer T } ? T : never;

type ReadonlyStoreApi<T> = Pick<StoreApi<T>, "getState" | "subscribe">;

type WithReact<S extends ReadonlyStoreApi<unknown>> = S & {
  getServerState?: () => ExtractState<S>;
};

// 核心方法create逻辑转移给createImpl，直接看createImpl
export function create<T>(createState: StateCreator<T>) {
  return createImpl(createState);
}

function createImpl<T>(createState: StateCreator<T>) {
  // createStore创建state对象，同时对state对象的使用行为进行subscribe收集依赖，对对象的set行为进行依赖触发
  const api = createStore(createState);

  // useStore将state对象与react连接——组件中使用状态时收集组件更新的回调函数
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const useBoundStore: any = () => useStore(api);

  return useBoundStore;
}

// createStore除了调用入参createState函数创建state之外，最主要的就是创建state对象的get/set/subscribe方法
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const createStore = (createState: any) => {
  type TState = ReturnType<typeof createState>;
  type Listener = (state: TState, prevState: TState) => void;

  let state: TState;
  const listeners: Set<Listener> = new Set();

  // setState负责：1、修改state 2、触发Listeners
  const setState: StoreApi<TState>["setState"] = (partial, replace) => {
    const nextState = typeof partial === "function" ? partial(state) : partial;

    if (!Object.is(nextState, state)) {
      const previousState = state;
      // let test = false ?? true ? 1 : 2; test值为2，正确的断句：(false ?? true) ? 1 : 2，也就是说??会结合后面紧跟的一个值作为一个整体，充当三元运算符的一部分，表达式(A ?? B)只有当A为null/undefined时，给表达式一个默认值为B
      // 若不传replace值，typeof nextState !== "object"决定三元运算符的所走分支，如果nextState为对象，则默认进行对象合并；若replace为true，直接将state赋值为nextState，即进行对象替换
      state =
        replace ?? typeof nextState !== "object"
          ? nextState
          : Object.assign({}, state, nextState);

      listeners.forEach((listener) => listener(state, previousState));
    }
  };
  // 返回state
  const getState: StoreApi<TState>["getState"] = () => state;
  // 提供订阅state的方法
  const subscribe: StoreApi<TState>["subscribe"] = (listener: Listener) => {
    listeners.add(listener);

    return () => listeners.delete(listener);
  };

  // 清除所有订阅
  const destroy: StoreApi<TState>["destroy"] = () => {
    listeners.clear();
  };

  const api = {
    getState,
    setState,
    subscribe,
    destroy,
  };

  // 调用createState来创建state对象
  state = createState(setState, getState, api);

  return api;
};

// 通过useSyncExternalStore让react组件来订阅state
function useStore<TState>(api: WithReact<StoreApi<TState>>) {
  const slice = useSyncExternalStore(api.subscribe, api.getState);

  return slice;
}

interface BearState {
  bears: number;
  increase: (by?: number) => void;
  decrease: (by?: number) => void;
  reset: () => void;
}

const useBearStore = create<BearState>((set) => ({
  bears: 0,
  increase: (by = 1) => set((state) => ({ bears: state.bears + by })),
  decrease: (by = 1) => set((state) => ({ bears: state.bears - by })),
  reset: () => set({ bears: 0 }),
}));

export default useBearStore;
